feat: Tab/Shift+Tab navigation and F2 inline edit for label list#262
Open
phobo3s wants to merge 16 commits into
Open
feat: Tab/Shift+Tab navigation and F2 inline edit for label list#262phobo3s wants to merge 16 commits into
phobo3s wants to merge 16 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds keyboard-first navigation and inline editing for OCR detection results to reduce mouse usage during correction workflows.
Changes:
- Adds Tab / Shift+Tab navigation across label list items, and F2 (plus Enter/Return handling) to trigger inline editing.
- Introduces
_navigateLabel()to programmatically advance selection and keep the selected item visible/focused. - Extends
EditInListwithactivate_edit()and updates Enter behavior in edit mode to advance to the next item.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| PPOCRLabel.py | Wires new shortcuts/keypress handlers and adds _navigateLabel() for label navigation + focus behavior. |
| libs/editinlist.py | Adds activate_edit() and modifies Enter handling to close the editor, advance selection, and re-open editing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import signal | ||
| import subprocess | ||
| import sys | ||
| import torch |
Comment on lines
+1365
to
+1366
| self.focusAndZoom() # ← Ctrl+G'nin yaptığı | ||
| self.labelList.activate_edit() # ← F2'nin yaptığı |
Comment on lines
+43
to
+53
| def keyPressEvent(self, event) -> None: | ||
| # close edit | ||
| if event.key() in [16777220, 16777221]: | ||
| if event.key() in [16777220, 16777221]: # Enter / Return | ||
| for i in range(self.count()): | ||
| self.closePersistentEditor(self.item(i)) | ||
| # bir sonraki satıra geç ve editörü aç | ||
| next_row = self.currentRow() + 1 | ||
| if next_row < self.count(): | ||
| self.setCurrentRow(next_row) | ||
| self.scrollToItem(self.item(next_row)) | ||
| self.activate_edit() No newline at end of file |
Comment on lines
+1362
to
+1364
| self.labelList.setCurrentRow(next_row) | ||
| self.labelList.scrollToItem(self.labelList.item(next_row)) | ||
| self.labelSelectionChanged() |
- Remove unused `import torch` (caused ImportError for users without PyTorch) - Remove redundant `labelSelectionChanged()` call in `_navigateLabel()` since setCurrentRow() already triggers the connected itemSelectionChanged signal - Remove auto `activate_edit()` from `_navigateLabel()`: Tab navigates only, F2 opens editor (matches PR description) - Fix `EditInList.keyPressEvent`: call `event.accept()` + return on Enter, fall through to `super().keyPressEvent()` for all other keys so arrow keys and normal list navigation keep working https://claude.ai/code/session_01SSG7xRPGp19iVAs9UPDPPb
- Tab: close editor (save), move to next item, open editor there - Shift+Tab: close editor (save), move to previous item, open editor there - Enter/Return: close editor (save), move to next item (no auto-edit) - Extract _close_editors() helper to avoid repetition https://claude.ai/code/session_01SSG7xRPGp19iVAs9UPDPPb
QLineEdit (the persistent editor widget) was consuming Tab for focus traversal before EditInList.keyPressEvent ever saw it. Install an eventFilter on the editor widget in activate_edit() so Tab/Shift+Tab are intercepted at the source, closing the editor (saving the value) and advancing to the next/previous item with a fresh editor open. https://claude.ai/code/session_01SSG7xRPGp19iVAs9UPDPPb
closePersistentEditor does not flush the QLineEdit value back to the model (it closes with NoHint). Call commitData(editor) first so the typed text is actually saved before navigation happens. https://claude.ai/code/session_01SSG7xRPGp19iVAs9UPDPPb
Root cause: Qt fires QShortcut BEFORE the key event reaches the focused widget. The Tab QShortcut was navigating without saving, and the eventFilter on the QLineEdit was never called (event consumed by shortcut). Fix: - Remove Tab/Shift+Tab QShortcuts and keyPressEvent handlers from MainWindow - In EditInList.eventFilter: intercept Tab/Shift+Tab from the QLineEdit, call commitData() to flush value to model, then navigate and reopen editor - In EditInList.keyPressEvent: handle Tab when no editor is open (plain nav) - Rename _close_editors to _commit_and_close to make intent clear https://claude.ai/code/session_01SSG7xRPGp19iVAs9UPDPPb
Previous attempts failed because editItem() and openPersistentEditor() create two separate QLineEdit widgets; the eventFilter was installed on the wrong one. Also commitData() on a persistent editor does not flush the typed text. New approach: - Install a QApplication-level eventFilter when editing starts (catches Tab from whichever QLineEdit child actually has focus) - Save by finding the visible QLineEdit child and calling item.setText() directly — bypasses all delegate machinery, guaranteed to work - Remove the app filter when editing ends to avoid side effects https://claude.ai/code/session_01SSG7xRPGp19iVAs9UPDPPb
Adds a dock widget with a slider (0–1.00) on the right panel. Boxes with OCR confidence >= threshold are hidden; only those below the threshold are drawn. Default = 1.00 shows everything. Implementation: - Shape.score attribute stores OCR rec_score (None if not from OCR) - After autoRecognitionCurrent, scores are copied from result_dic to shapes - applyConfidenceFilter() calls canvas.setShapeVisible() per shape - Slider re-runs the filter on every change https://claude.ai/code/session_01SSG7xRPGp19iVAs9UPDPPb
Removing torch caused c10.dll errors on Windows when PaddlePaddle is installed alongside PyTorch. Keep the import with a noqa marker so flake8 doesn't flag it as unused. https://claude.ai/code/session_01SSG7xRPGp19iVAs9UPDPPb
Score is saved as an optional 'score' field in Label.txt entries (backwards compatible — old files without it load fine, score=None). Changes: - saveLabels: write score from result_dic and from shape.score - loadLabels: read score from tuple item[4], set shape.score - showBoundingBoxFromPPlabel: pass score through tuples, call filter after load - locked shapes pass None score (no OCR confidence available) Slider now filters correctly both after OCR and after re-opening saved files. https://claude.ai/code/session_01SSG7xRPGp19iVAs9UPDPPb
When a box is selected, the Confidence Filter dock label updates to show both the current threshold and the selected shape's score: "Threshold: 0.87 | Selected: 0.73" https://claude.ai/code/session_01SSG7xRPGp19iVAs9UPDPPb
findChildren(QLineEdit) was finding the wrong widget. The focused widget IS the QLineEdit the user is typing in, so use that directly. Falls back to findChildren only if focusWidget is not a QLineEdit. https://claude.ai/code/session_01SSG7xRPGp19iVAs9UPDPPb
Wire EditInList.navigated signal to MainWindow.focusAndZoom so that pressing Tab/Shift+Tab while editing labels also triggers the same canvas centering and zoom that Ctrl+G provides. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SSG7xRPGp19iVAs9UPDPPb
Add pyqtSignal import and navigated signal declaration, then emit it after every Tab/Shift+Tab move in both eventFilter (editor open) and keyPressEvent (no editor open). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SSG7xRPGp19iVAs9UPDPPb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds keyboard shortcuts for navigating and editing OCR detection results without mouse clicks.
Shortcuts added
TabShift+TabF2EnterMotivation
When correcting OCR output on a dense document (50–200 boxes), the current workflow requires a mouse click for every single box. With these shortcuts, the entire correction pass can be done keyboard-only — Tab to navigate, F2 to edit, Enter to confirm and continue.
This pattern is standard in annotation tools (LabelImg, Label Studio, CVAT).
Changes
PPOCRLabel.py: AddedQShortcutbindings for Tab/Shift+Tab/F2, added_navigateLabel()methodlibs/editinlist.py: Addedactivate_edit()method, Enter in edit mode now moves to next itemcloses #261